<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Tweets for the Tweet</title>
    <script src="../../js/jquery.js" type="text/javascript"></script>
    <script src="../../js/gestalt.js" type="text/javascript"></script>
    <style type="text/css">
        BODY{background: #000000; color: #FFFFFF;}
    </style>
</head>
<body>

<script language="python">
from System import *
from System.Windows import *
from System.Windows.Threading import *
from System.Windows.Media import *
from System import *
from System.Net import *
from System.Text import *
from System.Collections import *
from System.Collections.Specialized import *
from System.Windows.Media.Imaging import *
from System.Diagnostics import *

from System.Text.RegularExpressions import *

URLS = {
		"auth" : "http://twitter.com/account/verify_credentials.json",
		"friends" : "http://twitter.com/statuses/friends_timeline.json",
		"update" : "http://twitter.com/statuses/update.json",
		"search" : "http://search.twitter.com/search.json"
}

keyword = "gestalt"

#tweets = [{"name":"Gestalt", "image_url":"http://assets0.twitter.com/images/twitter.png", "text":"loading tweets. Click buttons to read more!", "created_at":DateTime.Now.ToShortDateString(), "source":"gestalt"}]
tweets = [{"name":"", "image_url":"", "text":"", "created_at":"", "source":"", "id":""}]
current_tweet = -1
qs = None

class Twitter:
	""" I deal with talking to Twitter. """
	def __init__(self):
	    self.hash = ""
	    self.presenters = []

	def credentials(username, password):
	    utf8 = UTF8Encoding();
	    self.hash = Convert.ToBase64String(utf8.GetBytes("%s:%s" % (username,password)))

	def add_presenter(self, presenter_instance):
	    self.presenters.append(presenter_instance)

	def friends_timeline(self):
		""" I get your friends' update """
		url = "%s" % URLS["friends"]
		self.fetch(url)

	def update(self, msg):
		""" I make updates for you. """
		url = "%s?status=%s" % (URLS["update"], msg)
		self.fetch(url, "POST")

	def search(self, query_terms, query_string=None):
	    """ Search for anything you want. I'll find it. You choose how to use the results. """
	    url = URLS["search"]
	    if(query_string):
	        url += query_string
	    else:
	        url += "?q=" + query_terms
	    self.fetch(url)

	def update_status_list(self, sender, args):
		if (args.Error == None):
			resp = JsonValue.Parse(args.Result)
			for presenter in self.presenters:
				presenter.add_to_status_list(resp)
		else:
			log(args.Error)

	def fetch(self, uri, method="GET"):
		client = WebClient()
		
		### Uncoment these only if you wish to have the server cache tweets on behalf of all your users to avoid rate limiting. On the web though all users will be using their own
		### IP addresses, so this is not as much an issue as when you are developing against this code from one IP address and making many calls.
		#online version
		#proxy = str("http://www.visitmix.com/labs/gestalt/samples/twitter.badge/TwitterProxy.ashx?u=%s&m=%s" % (HttpUtility.UrlEncode(uri), HttpUtility.UrlEncode(method)))
		#http://www.visitmix.com/labs/gestalt/samples/twitter.badge/TwitterProxy.ashx?u=http%3a%2f%2fsearch.twitter.com%2fsearch.json%3ftag%3dgestalt&m=GET
		#VS version
		#proxy = str("http://localhost:54151/samples/twitter.badge/TwitterProxy.ashx?u=%s&m=%s" % (HttpUtility.UrlEncode(uri), HttpUtility.UrlEncode(method)))
		#http://localhost/gestalt/TwitterProxy.ashx?u=http%3a%2f%2fsearch.twitter.com%2fsearch.json%3ftag%3dgestalt&m=GET
		#http://localhost:54151/samples/twitter.badge/TwitterProxy.ashx?u=http%3a%2f%2fsearch.twitter.com%2fsearch.json%3ftag%3dgestalt&m=GET
		#if(self.hash):
		#    proxy += "&ph=%s" % HttpUtility.UrlEncode(self.hash)
		#log(proxy)
		#client.DownloadStringAsync(Uri(proxy))
		
		
		client.DownloadStringAsync(Uri(uri))
		
		client.DownloadStringCompleted += self.update_status_list

class BadgePresenter():
    def add_to_status_list(self, json):
        global qs
        qs = json.refresh_url
        #log(json.results)
        tweets.Clear()
        for status in json.results:
            tweets.append({"name":status.from_user, "image_url":status.profile_image_url.Replace("\\",""), "text":status.text, "created_at":DateTime.Parse(status.created_at).ToShortDateString(), "source":status.source, "id":status.id})
        go_to_next_tweet(None, None) #trigger immediately
                    
def ping_twitter(sender, args):
    twitter.search(None, "?tag=" + keyword)
    log("called %s" % DateTime.Now.ToString())

def move_next(sender, args):
    go_to_next_tweet(sender, args)

def go_to_next_tweet(sender, args):
    global current_tweet
    if(current_tweet < len(tweets)-1):
        current_tweet += 1
    else:
        current_tweet = 0
    update_ui(tweets[current_tweet])

def go_to_previous_tweet(sender, args):
    global current_tweet
    if(current_tweet >= 1):
        current_tweet -= 1
    else:
        current_tweet = len(tweets)-1
    update_ui(tweets[current_tweet])

def update_ui(data_hash):
    me.badge.fade_out.Begin()
    me.status.Text = Regex.Unescape(data_hash["text"])
    #me.details.Text = "from %s on %s from %s" % (data_hash["name"], data_hash["created_at"], data_hash["source"])
    
    if data_hash["name"] != "":
        me.details.Text = "from %s on %s" % (data_hash["name"], data_hash["created_at"])
        
    imageUrl = data_hash["image_url"]
    
    if imageUrl.Contains(".gif"):
        me.Loading.Visibility = Visibility.Collapsed
    
    if imageUrl.Contains(".gif") or imageUrl == "":
        imageUrl = "http://assets0.twitter.com/images/twitter.png"
    else:
        me.Loading.Visibility = Visibility.Collapsed
    
    if data_hash.has_key('id'):
        url = "http://www.twitter.com/" + data_hash["name"] + "/statuses/" + data_hash["id"].ToString()
        me.MainRect.DataContext = url
        log(url)
		
    me.avatar.Source = BitmapImage(Uri(imageUrl))
    
    me.badge.fade_in.Begin()
    
def mouse_enter(sender, e):
    sender.Fill = SolidColorBrush(Color.FromArgb(0xFF,0xC5,0xE6,0xF9))

def mouse_leave(sender, e):
    sender.Fill = SolidColorBrush(Color.FromArgb(0xFF,0xD4,0xE9,0xF5))

def browse(sender, e):
    url = me.MainRect.DataContext
    if url != "http://www.twitter.com//statuses/":
        HtmlPage.Window.Navigate(Uri(url), "_blank");

def log(msg):
    #document.msg.innerHTML = "<p>"+str(msg)+"</p>"
    Debug.WriteLine(str(msg))
    
twitter = Twitter()
twitter.add_presenter(BadgePresenter())
twitter.search(None, "?tag=" + keyword)


ping_timer = DispatcherTimer(Interval = TimeSpan(0, 0, 0, 120, 0))
ping_timer.Tick += ping_twitter
ping_timer.Start()

cross_fader = DispatcherTimer(Interval = TimeSpan(0, 0, 0, 10, 0))
cross_fader.Tick += move_next
cross_fader.Start()

me.next.MouseLeftButtonDown += go_to_next_tweet
me.next.MouseEnter +=  mouse_enter
me.next.MouseLeave +=  mouse_leave

me.previous.MouseLeftButtonDown += go_to_previous_tweet
me.previous.MouseEnter +=  mouse_enter
me.previous.MouseLeave +=  mouse_leave

me.MainRect.MouseLeftButtonDown +=  browse
me.MainRect.MouseEnter +=  mouse_enter
me.MainRect.MouseLeave +=  mouse_leave
</script>

<xml id="twitter_badge" class="xaml" Width="580" Height="180">
<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  xmlns:xaml="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="badge" Width="580" Height="180">
    <Canvas.Resources>
        <Storyboard x:Name="fade_out">
            <DoubleAnimation Storyboard.TargetName="status" Storyboard.TargetProperty="Opacity" From="1.0" To="0.0" Duration="0:0:.5"></DoubleAnimation>
       </Storyboard>
        <Storyboard x:Name="fade_in">
            <DoubleAnimation Storyboard.TargetName="status" Storyboard.TargetProperty="Opacity" From="0.0" To="1.0" Duration="0:0:.5"></DoubleAnimation>
       </Storyboard>
    </Canvas.Resources>
    
    <Rectangle xaml:Canvas.Left="108" xaml:Canvas.Top="15" Width="450" Height="130" RadiusX="10" RadiusY="10" Fill="#FFD4E9F5" x:Name="MainRect"  Cursor="Hand"></Rectangle>
    <TextBlock xaml:Canvas.Left="126" xaml:Canvas.Top="27" Width="420" x:Name="status" FontSize="22" TextWrapping="Wrap" Height="104" FontFamily="Georgia" Text="" Foreground="#FF035FA4" IsHitTestVisible="False"></TextBlock>
    <TextBlock xaml:Canvas.Left="126" xaml:Canvas.Top="149" x:Name="details" Width="300" Height="20" FontFamily="Georgia" Text="" FontSize="14" IsHitTestVisible="False"></TextBlock>
    <Rectangle Height="60" Width="60" xaml:Canvas.Left="19" xaml:Canvas.Top="27" Fill="#FFD4E9F5" RadiusX="10" RadiusY="10"></Rectangle>
    <xaml:Image x:Name="avatar" Width="60" Height="60" xaml:Canvas.Top="27" xaml:Canvas.Left="19" Clip="M0,10 C0,4.4771523 4.4771523,0 10,0 L50,0 C55.522846,0 60,4.4771523 60,10 L60,50 C60,55.522846 55.522846,60 50,60 L10,60 C4.4771523,60 0,55.522846 0,50 z"></xaml:Image>
    
    <Canvas x:Name="Loading" xaml:Canvas.Left="247" xaml:Canvas.Top="55">
        <Rectangle Fill="#FF000000" RadiusX="10" RadiusY="10" StrokeThickness="0" VerticalAlignment="Top" Width="132" HorizontalAlignment="Left" Height="43" Opacity="0.2" xaml:Canvas.Top="2" xaml:Canvas.Left="2"></Rectangle>
	    <TextBlock FontFamily="Arial" FontSize="20" Foreground="#FF000000" Text="loading..." TextWrapping="Wrap" Width="132.852" Height="29" xaml:Canvas.Top="12" xaml:Canvas.Left="29" Opacity="0.75"></TextBlock>
	</Canvas>
    <xaml:Ellipse Height="4.703" Width="4.703" xaml:Canvas.Left="82.114" xaml:Canvas.Top="55.608" Fill="#FFD4E9F5"></xaml:Ellipse>
    <xaml:Ellipse Height="8.053" Width="8.053" xaml:Canvas.Left="88.951" xaml:Canvas.Top="49.015" Fill="#FFD4E9F5"></xaml:Ellipse>
    <xaml:Ellipse Height="11.755" Width="11.755" Fill="#FFD4E9F5" xaml:Canvas.Left="92.492" xaml:Canvas.Top="35.671"></xaml:Ellipse>
    <xaml:Ellipse x:Name="previous" Height="20" Width="20" Fill="#FFD4E9F5" xaml:Canvas.Top="98.096" xaml:Canvas.Left="27.298" Cursor="Hand"></xaml:Ellipse>
    <xaml:Ellipse x:Name="next" Height="20" Width="20" Fill="#FFD4E9F5" xaml:Canvas.Left="51.616" xaml:Canvas.Top="98.096"  Cursor="Hand"></xaml:Ellipse>
    <xaml:Path Height="7.894" Width="8.386" xaml:Canvas.Left="34.398" xaml:Canvas.Top="104.14" Fill="#FF222222" Stretch="Fill" Data="M53.495468,97.611855 L53.495468,107.33817 L43.422112,107.33817 L53.669647,97.090668" RenderTransformOrigin="0.5,0.5" Opacity="0.195"  Cursor="Hand"  IsHitTestVisible="False">
    	<xaml:Path.RenderTransform>
    		<xaml:TransformGroup>
    			<xaml:ScaleTransform></xaml:ScaleTransform>
    			<xaml:SkewTransform></xaml:SkewTransform>
    			<xaml:RotateTransform Angle="135"></xaml:RotateTransform>
    			<xaml:TranslateTransform></xaml:TranslateTransform>
    		</xaml:TransformGroup>
    	</xaml:Path.RenderTransform>
    </xaml:Path>
    <xaml:Path Height="7.817" Width="7.817" Fill="#FF222222" Stretch="Fill" Data="M53.495468,97.611855 L53.495468,107.33817 L43.422112,107.33817 L53.669647,97.090668" RenderTransformOrigin="0.5,0.5" Opacity="0.195" xaml:Canvas.Left="56.059" xaml:Canvas.Top="104.367"  Cursor="Hand"  IsHitTestVisible="False">
    	<xaml:Path.RenderTransform>
    		<xaml:TransformGroup>
    			<xaml:ScaleTransform ScaleY="-1" ScaleX="-1"></xaml:ScaleTransform>
    			<xaml:SkewTransform></xaml:SkewTransform>
    			<xaml:RotateTransform Angle="135"></xaml:RotateTransform>
    			<xaml:TranslateTransform></xaml:TranslateTransform>
    		</xaml:TransformGroup>
    	</xaml:Path.RenderTransform>
    </xaml:Path>
</Canvas>
</xml>

<div id="msg"> </div>
</body>
</html>